use std::cell::RefCell;
use std::rc::Rc;
use crate::instruction::instruction::Instruction;
use crate::vm_thread::{VMFrame, VMThread};
use crate::vm_val::{VMValEnum, VMValInteger, VMValLong, VMValRef};

pub struct dup {}

impl Instruction for dup {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        let ro_frame = frame.borrow();
        let mut operand_stack = ro_frame.operand_stack.borrow_mut();
        let option_val = operand_stack.pop();
        if option_val.is_none() {
            panic!("操作数栈为空");
        }
        match option_val.unwrap() {
            VMValEnum::VMValLong { val } => {
                operand_stack.push(VMValEnum::VMValLong { val: VMValLong { num: val.num } });
                operand_stack.push(VMValEnum::VMValLong { val })
            }
            VMValEnum::VMValInteger { val } => {
                operand_stack.push(VMValEnum::VMValInteger { val: VMValInteger { num: val.num } });
                operand_stack.push(VMValEnum::VMValInteger { val })
            }
            VMValEnum::VMValRef { val } => {
                operand_stack.push(VMValEnum::VMValRef { val: VMValRef { num: val.num } });
                operand_stack.push(VMValEnum::VMValRef { val })
            }
            _ => {}
        }
    }

    fn to_string(&self) -> String {
        String::from("dup")
    }
}